package cn.cjlmonster.demo02.pkg;

import java.nio.ByteBuffer;

public class PkgUtils {

    private static byte[] intToMinByteArray(int i) {
        byte[] result = new byte[4];
        result[3] = (byte) ((i >> 24) & 0xFF);
        result[2] = (byte) ((i >> 16) & 0xFF);
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    private static byte[] shortToMinByteArray(short i) {
        byte[] result = new byte[2];
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    public static byte[] reverseToMinByteArray(byte[] buffer) {
        byte[] result = new byte[buffer.length];
        for (int i = buffer.length - 1, j = 0; i >= 0; i--, j++) {
            result[j] = buffer[i];
        }
        return result;
    }

    public static byte[] hexStringToByteArray(String data, int len) {
        StringBuilder sb = new StringBuilder(data);
        sb.reverse();
        while (sb.length() < 2 * len) sb.append("0");
        sb.reverse();
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            int j = i * 2;
            String s = sb.substring(j, j + 2);
            result[i] = (byte) Integer.parseInt(s, 16);
        }
        return result;
    }

    public static byte getCRC8(byte[] buffer, byte key) {
        short i;
        byte crc;
        crc = 0;
        int ptr = 0;
        int len;
        len = buffer.length;
        while (len-- != 0) {
            for (i = 0x80; i != 0; i >>= 1) {
                if ((crc & 0x80) != 0) {
                    crc <<= 1;
                    crc ^= key;
                } else {
                    crc <<= 1;
                }
                if ((buffer[ptr] & i) != 0) {
                    crc ^= key;
                }
            }
            ptr++;
        }
        return (byte) (crc & 0xFF);
    }

    public static byte getCRC8(byte[] buffer) {
        return getCRC8(buffer, (byte) 0x93);
    }

    private static int serialNumber = 0;

    private static byte getSerialNumber() {
        if (serialNumber++ >= 255) serialNumber = 0;
        return (byte) serialNumber;
    }

    public static byte currentSerialNumber() {
        return (byte) serialNumber;
    }

    public static byte[] createCmd(byte serialNumber, String device, int cmd, byte[] data) {
        if (data == null) data = new byte[0];
        byte[] bootArray = shortToMinByteArray((short) 0xAA55);
        byte command = (byte) cmd;
        //        byte[] deviceArray = reverseToMinByteArray(hexStringToByteArray(device, 8));
        byte[] deviceArray = hexStringToByteArray(device, 8);
        int dataLength = 2 + 1 + 8 + 1 + 1 + data.length + 1;
        byte[] lengthArray = shortToMinByteArray((short) dataLength);

        ByteBuffer pkg = ByteBuffer.allocate(2 + 1 + 8 + 1);
        pkg.put(lengthArray);
        pkg.put(serialNumber);
        pkg.put(deviceArray);
        pkg.put(command);

        byte crc1 = getCRC8(pkg.array());

        byte crc2 = data.length == 0 ? 0 : getCRC8(data);

        ByteBuffer cmdArray = ByteBuffer.allocate(bootArray.length + dataLength);
        cmdArray.put(bootArray);
        cmdArray.put(pkg.array());
        cmdArray.put(crc1);
        cmdArray.put(data);
        cmdArray.put(crc2);
        return cmdArray.array();
    }

    public static byte[] createCmd(String device, int cmd, byte[] data) {
        return createCmd(getSerialNumber(), device, cmd, data);
    }

}
